home *** CD-ROM | disk | FTP | other *** search
/ IRIX Base Documentation 2001 May / SGI IRIX Base Documentation 2001 May.iso / usr / share / catman / p_man / cat5 / refcnt.z / refcnt
Encoding:
Text File  |  2001-04-17  |  103.1 KB  |  2,509 lines

  1.  
  2.  
  3.  
  4. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  5.  
  6.  
  7.  
  8. NNNNAAAAMMMMEEEE
  9.      MMMMeeeemmmmoooorrrryyyy RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss - Analysis of memory access patterns
  10.  
  11.  
  12. DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  13.      The Origin hardware and Cellular Irix provide memory reference counters
  14.      to assist application programmers in tuning their algorithms for optimal
  15.      performance on a NUMA system. These counters are capable of unveiling the
  16.      exact memory reference patterns exhibited by an application or a specific
  17.      algorithm, enabling the programmer to optimize the application data
  18.      layout and to provide specific memory placement hints to the Operating
  19.      System in order to maximize cache utilization and locality of memory
  20.      access, therefore achieving best memory access performance.
  21.  
  22.  
  23. IIIIMMMMPPPPLLLLEEEEMMMMEEEENNNNTTTTAAAATTTTIIIIOOOONNNN
  24.    HHHHaaaarrrrddddwwwwaaaarrrreeee RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss
  25.      Origin 2000 and Origin 200 systems provide a set of counters for every 4
  26.      KB hardware page of memory. The number of counters per set depends on the
  27.      number of nodes in the system: for systems with less than 64 nodes (that
  28.      is 128 processors) a counter set has one counter per node, and for
  29.      systems with more than 64 nodes a counter set has one counter for every 8
  30.      nodes. For systems with 64 or less nodes, each counter in a counter set
  31.      counts the numbers of references from each of the nodes. Thus, the
  32.      application programmer can tell exactly how many references have been
  33.      issued to a page from each node in the system. For systems with more than
  34.      64 nodes, each counter in a  counter set corresponds to the number of
  35.      references to a page issued by a group of 8 nodes.
  36.  
  37.      Note that a hhhhaaaarrrrddddwwwwaaaarrrreeee ppppaaaaggggeeee is not equivalent to a bbbbaaaasssseeee ssssooooffffttttwwwwaaaarrrreeee ppppaaaaggggeeee (or
  38.      just ppppaaaaggggeeee). A hhhhaaaarrrrddddwwwwaaaarrrreeee ppppaaaaggggeeee defines the granularity at with the hardware
  39.      does reference counting and other hardware operations; a base software
  40.      page is the smallest unit of memory that can be mapped by user processes
  41.      via the Translation Look-aside Buffer or the Page Tables. For Origin 2000
  42.      and Origin 200 systems a hardware page, and therefore the memory
  43.      reference counting granularity, is 4 KB; and a base sofware page is 16KB.
  44.  
  45.      For example, consider an 8 node (16 cpu) Origin 2000 system with the
  46.      memory configuration shown in the table below. This table shows the
  47.      number of hardware pages (equivalent to the number of counter sets), the
  48.      number of total counters, and the number of base software pages per node.
  49.      For this configuration of 8 nodes, each counter set has 8 counters (one
  50.      per node).
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.                                                                         PPPPaaaaggggeeee 1111
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  71.  
  72.  
  73.  
  74.                                   Memory Configuration
  75.                                   Hardware   Counter    Total          Base
  76.                         Memory     Pages      Sets     Counters   Software Pages
  77.         Module   Slot   [bytes]   Mem/4Kb    1/Hpage    8*Sets       Mem/16Kb
  78.           1       n1     512M       128K      128K      1024K          32K
  79.           1       n2     256M        65K       65K       512K          16K
  80.           1       n3     256M        65K       65K       512K          16K
  81.           1       n4     512M       128K      128K      1024K          32K
  82.           2       n1     256M        65K       65K       512K          16K
  83.           2       n2      64M        16K       16K       128K           4K
  84.           2       n3      64M        16K       16K       128K           4K
  85.           2       n4     256M        65K       65K       512K          16K
  86.  
  87.  
  88.      The length of each counter also depends on the system configuration.  For
  89.      systems with more than 16 nodes (32 cpus), the counters have a length of
  90.      19 bits (maximum count is 0x7ffff). For systems with less than 16 nodes,
  91.      the length of the counters depends on the the kind of directory SIMMS
  92.      installed on the machine. If SSSSTTTTAAAANNNNDDDDAAAARRRRDDDD SSSSIIIIMMMMMMMMSSSS are installed, then the
  93.      counters are 11-bit (maximum count 0x7ff); if PPPPRRRREEEEMMMMIIIIUUUUMMMM SSSSIIIIMMMMMMMMSSSS are
  94.      installed, then the counters are 19-bit.
  95.  
  96.  
  97.    SSSSooooffffwwwwaaaarrrreeee EEEExxxxtttteeeennnnddddeeeedddd RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss
  98.      The hardware counters peg when they reach their maximum count. This is a
  99.      problem for the 11-bit counters that would peg after only 0x7ff (2047)
  100.      references to a page from one node. To allow application programmers to
  101.      keep track of memory references beyond this small number, Cellular Irix
  102.      provides SSSSooooffffttttwwwwaaaarrrreeee EEEExxxxtttteeeennnnddddeeeedddd MMMMeeeemmmmoooorrrryyyy RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss.
  103.  
  104.      The Extended Counters are implemented as an array of 32-bit counters that
  105.      closely mirror the hardware counters, extending their maximum count to
  106.      2^32.  The hardware counters are setup in such a way that they send an
  107.      interrupt when they reach a threshold close to the maximum count. When
  108.      this interrupt is received by the operating system, the current hardware
  109.      counter count is added to the corresponding software extended counter
  110.      mirror, and the hardware counter is reset to 0. This uuuuppppddddaaaatttteeee procedure is
  111.      performed for complete counter sets, that is, when we receive the
  112.      overflow interrupt we not only update the counter that is overflowing,
  113.      but also all the other counters in its set.
  114.  
  115.  
  116. IIIINNNNTTTTEEEERRRRFFFFAAAACCCCEEEE
  117.    EEEEnnnnaaaabbbblllliiiinnnngggg RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnnttttiiiinnnngggg
  118.      To enable reference counting for a section of virtual memory within an
  119.      application, the programmer can use a Policy Module (mmci(5)) with the
  120.      migration policy set to "MigrationRefcnt".
  121.  
  122.           void
  123.           refcnt_enable(char* vaddr, size_t len)
  124.           {
  125.                   pmo_handle_t pm;
  126.  
  127.  
  128.  
  129.                                                                         PPPPaaaaggggeeee 2222
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  137.  
  138.  
  139.  
  140.                   policy_set_t policy_set;
  141.  
  142.                   pm_filldefault(&policy_set);
  143.                   policy_set.migration_policy_name = "MigrationRefcnt";
  144.                   policy_set.migration_policy_args = NULL;
  145.  
  146.                   if ((pm = pm_create(&policy_set)) < 0) {
  147.                           perror("pm_create");
  148.                           exit(1);
  149.                   }
  150.  
  151.                   if (pm_attach(pm, vaddr, size) < 0) {
  152.                           perror("pm_attach");
  153.                           exit(1);
  154.                   }
  155.           }
  156.  
  157.  
  158.  
  159.    HHHHaaaarrrrddddwwwwaaaarrrreeee RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss
  160.      The hardware reference counters for a section of an address space can be
  161.      accessed using pppprrrrooooccccffffssss (proc(4)). The ioctl command code used for this
  162.      purpose is PIOCGETSN0REFCNTRS. The third argument is used to specify both
  163.      the virtual address space range we need the counters for, and the buffer
  164.      where the system should copy the counter values to. This argument is of
  165.      type sn0_refcnt_args_t, as defined in <sys/SN/hwcntrs.h>:
  166.  
  167.           typedef struct sn0_refcnt_args {
  168.                   caddr_t             vaddr;
  169.                   long                len;
  170.                   sn0_refcnt_buf_t*   buf;
  171.           } sn0_refcnt_args_t;
  172.  
  173.  
  174.      The first field vvvvaaaaddddddddrrrr is the base of the virtual address space range, the
  175.      field lllleeeennnn is the corresponding length in bytes, and the field bbbbuuuuffff is a
  176.      pointer to a user buffer where the system will store the counter values
  177.      and additional information. This buffer is an array of elements of type
  178.      sn0_refcnt_buf_t, where each element corresponds to the counter
  179.      information associated with one hardware page:
  180.  
  181.           typedef struct sn0_refcnt_buf {
  182.                sn0_refcnt_set_t   refcnt_set;
  183.                __uint64_t         paddr;
  184.                   __uint64_t         page_size;
  185.                   cnodeid_t          cnodeid;
  186.           } sn0_refcnt_buf_t;
  187.  
  188.  
  189.      The field rrrreeeeffffccccnnnntttt____sssseeeetttt contains the set of counters associated with the
  190.      virtual address passed via ssssnnnn0000____rrrreeeeffffccccnnnntttt____aaaarrrrggggssss, ppppaaaaddddddddrrrr is the address of the
  191.      physical page associated with this virtual address, ppppaaaaggggeeee____ssssiiiizzzzeeee is the page
  192.  
  193.  
  194.  
  195.                                                                         PPPPaaaaggggeeee 3333
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  203.  
  204.  
  205.  
  206.      size being used to map it, and ccccnnnnooooddddeeeeiiiidddd is the physical page home node,
  207.      expressed in terms of _C_o_m_p_a_c_t _N_o_d_e _I_d_e_n_t_i_f_i_e_r_s which can be mapped back
  208.      to node names using the command topology(1).  The rrrreeeeffffccccnnnntttt____sssseeeetttt type is
  209.      defined by
  210.  
  211.           typedef struct sn0_refcnt_set {
  212.                   refcnt_t    refcnt[SN0_REFCNT_MAX_COUNTERS];
  213.                   __uint64_t  flags;
  214.           } sn0_refcnt_set_t;
  215.  
  216.  
  217.      The field rrrreeeeffffccccnnnntttt is the actual set of counters (one counter per node),
  218.      and ffffllllaaaaggggssss is a state vector reserved for future use.  The counters in
  219.      rrrreeeeffffccccnnnntttt are ordered according to the _C_o_m_p_a_c_t _N_o_d_e _I_d_e_n_t_i_f_i_e_r_s, also known
  220.      as ccccnnnnooooddddeeeeiiiiddddssss (numa(5)).
  221.  
  222.  
  223.  
  224.    SSSSooooffffttttwwwwaaaarrrreeee EEEExxxxtttteeeennnnddddeeeedddd RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss
  225.      The extended reference counters for a section of an address space can be
  226.      accessed using pppprrrrooooccccffffssss (proc(4)), using practically the same interface
  227.      defined above for the hardware reference counters.  The ioctl command
  228.      code used for this purpose is PIOCGETSN0EXTREFCNTRS (the difference
  229.      between this command and the command used for the hardware counters is
  230.      the prefix EXT before the word REFCNTRS). The third argument is used to
  231.      specify both the virtual address space range we need the counters for,
  232.      and the buffer where the system should copy the counter values to. This
  233.      argument is of type sn0_refcnt_args_t, as defined in <sys/SN/hwcntrs.h>:
  234.  
  235.           typedef struct sn0_refcnt_args {
  236.                   caddr_t             vaddr;
  237.                   long                len;
  238.                   sn0_refcnt_buf_t*   buf;
  239.           } sn0_refcnt_args_t;
  240.  
  241.  
  242.      The first field vvvvaaaaddddddddrrrr is the base of the virtual address space range, the
  243.      field lllleeeennnn is the corresponding length in bytes, and the field bbbbuuuuffff is a
  244.      pointer to a user buffer where the system will store the counter values
  245.      and additional information. This buffer is an array of elements of type
  246.      sn0_refcnt_buf_t, where each element corresponds to the counter
  247.      information associated with one hardware page:
  248.  
  249.           typedef struct sn0_refcnt_buf {
  250.                sn0_refcnt_set_t   refcnt_set;
  251.                __uint64_t         paddr;
  252.                   __uint64_t         page_size;
  253.                   cnodeid_t          cnodeid;
  254.           } sn0_refcnt_buf_t;
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.                                                                         PPPPaaaaggggeeee 4444
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  269.  
  270.  
  271.  
  272.      The field rrrreeeeffffccccnnnntttt____sssseeeetttt contains the set of counters associated with the
  273.      virtual address passed via ssssnnnn0000____rrrreeeeffffccccnnnntttt____aaaarrrrggggssss, ppppaaaaddddddddrrrr is the address of the
  274.      physical page associated with this virtual address, ppppaaaaggggeeee____ssssiiiizzzzeeee is the page
  275.      size being used to map it, and ccccnnnnooooddddeeeeiiiidddd is the physical page home node,
  276.      expressed in terms of _C_o_m_p_a_c_t _N_o_d_e _I_d_e_n_t_i_f_i_e_r_s which can be mapped back
  277.      to node names using the command topology(1).  The rrrreeeeffffccccnnnntttt____sssseeeetttt type is
  278.      defined by
  279.  
  280.           typedef struct sn0_refcnt_set {
  281.                   refcnt_t    refcnt[SN0_REFCNT_MAX_COUNTERS];
  282.                   __uint64_t  flags;
  283.           } sn0_refcnt_set_t;
  284.  
  285.  
  286.      The field rrrreeeeffffccccnnnntttt is the actual set of counters (one counter per node),
  287.      and ffffllllaaaaggggssss is a state vector reserved for future use.  The counters in
  288.      rrrreeeeffffccccnnnntttt are ordered according to the _C_o_m_p_a_c_t _N_o_d_e _I_d_e_n_t_i_f_i_e_r_s, also known
  289.      as ccccnnnnooooddddeeeeiiiiddddssss (numa(5)).
  290.  
  291.      The following routineshows how to access both the hardware counters and
  292.      the sofware extended counters using procfs.
  293.  
  294.           void
  295.           print_refcounters(char* vaddr, int len)
  296.           {
  297.                   pid_t pid = getpid();
  298.                   char  pfile[256];
  299.                   int fd;
  300.                   sn0_refcnt_buf_t* refcnt_buffer;
  301.                   sn0_refcnt_buf_t* direct_refcnt_buffer;
  302.                   sn0_refcnt_args_t* refcnt_args;
  303.                   int npages;
  304.                   int gen_start;
  305.                   int numnodes;
  306.                   int page;
  307.                   int node;
  308.                   char mem_node[512];
  309.                   refcnt_t* set_base;
  310.  
  311.                   sprintf(pfile, "/proc/%05d", pid);
  312.                   if ((fd = open(pfile, O_RDONLY)) < 0) {
  313.                     fprintf(stderr,"Can't open /proc/%d", pid);
  314.                     exit(1);
  315.                }
  316.  
  317.                   vaddr = (char *)( (unsigned long)vaddr & ~(hw_page_size-1) );
  318.                   npages = (len + (hw_page_size-1)) >> logb2(hw_page_size);
  319.  
  320.                   if ((refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  321.                           perror("malloc refcnt_buffer");
  322.                           exit(1);
  323.                   }
  324.  
  325.  
  326.  
  327.                                                                         PPPPaaaaggggeeee 5555
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  335.  
  336.  
  337.  
  338.  
  339.                   if ((direct_refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  340.                           perror("malloc refcnt_buffer");
  341.                           exit(1);
  342.                   }
  343.  
  344.                   if ((refcnt_args = malloc(sizeof(sn0_refcnt_args_t))) == NULL) {
  345.                           perror("malloc refcnt_args");
  346.                           exit(1);
  347.                   }
  348.  
  349.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  350.                   refcnt_args->len = len;
  351.                   refcnt_args->buf = refcnt_buffer;
  352.  
  353.                   if ((gen_start = ioctl(fd, PIOCGETSN0EXTREFCNTRS, (void *)refcnt_args)) < 0) {
  354.                     perror("ioctl  PIOCGETSN0EXTREFCNTRS returns error");
  355.                     exit(1);
  356.                }
  357.  
  358.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  359.                   refcnt_args->len = len;
  360.                   refcnt_args->buf = direct_refcnt_buffer;
  361.                   if ((gen_start = ioctl(fd, PIOCGETSN0REFCNTRS, (void *)refcnt_args)) < 0) {
  362.                     perror("ioctl  PIOCGETSN0REFCNTRS returns error");
  363.                     exit(1);
  364.                }
  365.  
  366.                   if ((numnodes = sysmp(MP_NUMNODES)) < 0) {
  367.                           perror("sysmp MP_NUMNODES");
  368.                           exit(1);
  369.                   }
  370.  
  371.                   for (page = 0; page < npages; page++) {
  372.                           printf("page[%05d, 0x%lx, 0x%llx (0x%llx)]:",
  373.                                  page,
  374.                                  vaddr + page*0x1000,
  375.                                  refcnt_buffer[page].paddr,
  376.                                  refcnt_buffer[page].paddr >> 14);
  377.                           for (node = 0; node < numnodes; node++) {
  378.                                   printf(" %ll05d (%ll06d)",
  379.                                          refcnt_buffer[page].refcnt_set.refcnt[node],
  380.                                          direct_refcnt_buffer[page].refcnt_set.refcnt[node]);
  381.                           }
  382.                           printf("0);
  383.                   }
  384.  
  385.                   close(fd);
  386.                   free(refcnt_args);
  387.                   free(refcnt_buffer);
  388.           }
  389.  
  390.  
  391.  
  392.  
  393.                                                                         PPPPaaaaggggeeee 6666
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  401.  
  402.  
  403.  
  404.    MMMMeeeemmmmoooorrrryyyy MMMMaaaappppppppeeeedddd SSSSooooffffttttwwwwaaaarrrreeee EEEExxxxtttteeeennnnddddeeeedddd RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss
  405.      The extended reference counters can also be accessed by mmapping them to
  406.      a user application's virtual address space. This interface is intended to
  407.      be used by performance tools that provide a global system view rather
  408.      than a localized process view.
  409.  
  410.      This interface is based on a device driver associated with a device that
  411.      represents the reference counters for each node in an Origin system.
  412.      Here is the list of reference counter devices for an 8 node system:
  413.  
  414.           /hw/module/2/slot/n1/node/refcnt
  415.           /hw/module/2/slot/n2/node/refcnt
  416.           /hw/module/2/slot/n3/node/refcnt
  417.           /hw/module/2/slot/n4/node/refcnt
  418.           /hw/module/1/slot/n1/node/refcnt
  419.           /hw/module/1/slot/n2/node/refcnt
  420.           /hw/module/1/slot/n3/node/refcnt
  421.           /hw/module/1/slot/n4/node/refcnt
  422.  
  423.  
  424.      To map the counters in a node, a user needs to open the refcnt device for
  425.      the node, then using the open file descriptor the user needs to obtain
  426.      information regarding the counters, defined by rcb_info_t in
  427.      <sys/SN/hwcntrs.h>, using ioctl(fd, RCB_INFO_GET, &rcbinfo).
  428.  
  429.           typedef struct rcb_info {
  430.                   __uint64_t  rcb_len;                  /* total refcnt buffer len in bytes */
  431.  
  432.                   int         rcb_sw_sets;              /* number of sw counter sets in buffer */
  433.                   int         rcb_sw_counters_per_set;  /* sw counters per set -- numnodes */
  434.                   int         rcb_sw_counter_size;      /* sizeof(refcnt_t) -- size of sw cntr */
  435.  
  436.                   int         rcb_base_pages;           /* number of base pages in node */
  437.                   int         rcb_base_page_size;       /* sw base page size */
  438.                   __uint64_t  rcb_base_paddr;           /* base physical address for this node */
  439.  
  440.                   int         rcb_cnodeid;              /* cnodeid for this node */
  441.                   int         rcb_granularity;          /* hw page size used for counter sets */
  442.                   uint        rcb_hw_counter_max;       /* max hwcounter count (width mask) */
  443.                   int         rcb_diff_threshold;       /* current node differential threshold */
  444.                   int         rcb_abs_threshold;        /* current node absolute threshold */
  445.                   int         rcb_num_slots;            /* physmem slots */
  446.  
  447.           } rcb_info_t;
  448.  
  449.  
  450.      Physical memory in a node is not always contiguous, and therefore
  451.      additional information is necessary to determine the counter buffer
  452.      location associated with a physical page. Physical memory within a node
  453.      is divided into a number of contiguous sections called "slots". The slot
  454.      configuration for a node can be obtained using ioctl(fd, RCB_SLOT_GET,
  455.      slotconfig), where slot config is of type rcb_slot_t defined in
  456.  
  457.  
  458.  
  459.                                                                         PPPPaaaaggggeeee 7777
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  467.  
  468.  
  469.  
  470.      <sys/SN/hwcntrs.h>.
  471.  
  472.           typedef struct rcb_slot {
  473.                   __uint64_t  base;    /* Base physical address for slot */
  474.                   __uint64_t  size;    /* Size of slot in bytes */
  475.           } rcb_slot_t;
  476.  
  477.  
  478.      The procedure below shows the complete sequence of operations required to
  479.      mmap the reference counters for all nodes. The counters in a buffer are
  480.      organized as follows:
  481.  
  482.  
  483.           Set for hardware page 0 in node /hw/module/1/slot/n2/node
  484.                counter for accesses from node with cnodeid 0
  485.                counter for accesses from node with cnodeid 1
  486.                ...
  487.                ...
  488.           Set for hardware page 1 in node /hw/module/1/slot/n2/node
  489.                counter for accesses from node with cnodeid 0
  490.                counter for accesses from node with cnodeid 1
  491.                ...
  492.                ...
  493.  
  494.  
  495.           /*
  496.            * Reference Counter Configuration for all nodes
  497.            */
  498.           rcb_info_t** rcbinfo;
  499.  
  500.           /*
  501.            * Physical Memory Config for all nodes
  502.            */
  503.           rcb_slot_t** slotconfig;
  504.  
  505.           /*
  506.            * Mapped counters for all nodes
  507.            */
  508.           refcnt_t** cbuffer;
  509.  
  510.  
  511.           void
  512.           mmap_counters(void)
  513.           {
  514.                   int fd;
  515.                   char refcnt[1024];
  516.                   refcnt_t* set_base;
  517.                   int numnodes;
  518.                   int node;
  519.  
  520.                   /* number of nodes */
  521.  
  522.  
  523.  
  524.  
  525.                                                                         PPPPaaaaggggeeee 8888
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  533.  
  534.  
  535.  
  536.                   numnodes = sysmp(MP_NUMNODES);
  537.  
  538.                   /* space for refcnt config -- just basic array for now */
  539.  
  540.                   rcbinfo = (rcb_info_t**)malloc(sizeof(rcb_info_t*) * numnodes);
  541.                   if (rcbinfo == NULL) {
  542.                           perror("malloc");
  543.                           exit(1);
  544.                   }
  545.  
  546.                   /* space for phys mem config -- just basic array for now*/
  547.  
  548.                   slotconfig = (rcb_slot_t**)malloc(sizeof(rcb_slot_t*) * numnodes);
  549.                   if (slotconfig == NULL) {
  550.                           perror("malloc");
  551.                           exit(1);
  552.                   }
  553.  
  554.                   /* space for array of pointers to the counter buffers */
  555.                   cbuffer = (refcnt_t**)malloc(sizeof(refcnt_t*) * numnodes);
  556.                   if (cbuffer == NULL) {
  557.                           perror("malloc");
  558.                           exit(1);
  559.                   }
  560.  
  561.                   for (node = 0; node < numnodes; node++) {
  562.                           sprintf(refcnt, "/hw/nodenum/%d/refcnt", node);
  563.                           if (verbose) {
  564.                                   printf("Opening dev %s0, refcnt);
  565.                           }
  566.  
  567.                           if ((fd = open(refcnt, O_RDONLY)) < 0) {
  568.                                   perror("open");
  569.                                   exit(1);
  570.                           }
  571.  
  572.                           /* get rcb info */
  573.  
  574.                           rcbinfo[node] = (rcb_info_t*)malloc(sizeof(rcb_info_t));
  575.                           if (rcbinfo[node] == NULL) {
  576.                                   perror("malloc");
  577.                                   exit(1);
  578.                           }
  579.  
  580.                           if (ioctl(fd, RCB_INFO_GET, rcbinfo[node]) < 0) {
  581.                                   perror("icctl RCB_INFO_GET");
  582.                                   exit(1);
  583.                           }
  584.  
  585.                           /* get phys mem config */
  586.  
  587.                           slotconfig[node] =
  588.  
  589.  
  590.  
  591.                                                                         PPPPaaaaggggeeee 9999
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  599.  
  600.  
  601.  
  602.                               (rcb_slot_t*)malloc(rcbinfo[node]->rcb_num_slots *
  603.                               sizeof(rcb_slot_t));
  604.                           if (slotconfig[node] == NULL) {
  605.                                   perror("malloc");
  606.                                   exit(1);
  607.                           }
  608.  
  609.                           if (ioctl(fd, RCB_SLOT_GET, slotconfig[node]) < 0) {
  610.                                   perror("ioctl RCB_SLOT_GET");
  611.                                   exit(1);
  612.                           }
  613.  
  614.                           /* map the counter buffer for this node */
  615.                           cbuffer[node] =
  616.                              (refcnt_t*)mmap(0,
  617.                                              rcbinfo[node]->rcb_len,
  618.                                              PROT_READ, MAP_SHARED, fd, 0);
  619.                           if (cbuffer[node] == (refcnt_t*)MAP_FAILED) {
  620.                                   perror("mmap");
  621.                                   exit(1);
  622.                           }
  623.  
  624.                           if (close(fd) <  0) {
  625.                                   perror("close");
  626.                                   exit(1);
  627.                           }
  628.  
  629.                   }
  630.           }
  631.  
  632.  
  633.  
  634.      All counters in a node are placed contiguously, but as mentioned earlier,
  635.      memory may not be contiguous. Therefore, the mapping between a physical
  636.      page and its set of counters needs to be done taking the memory gaps in
  637.      consideration, as shown below:
  638.  
  639.           uint
  640.           logb2(uint v)
  641.           {
  642.                   uint r;
  643.                   uint l;
  644.  
  645.                   r = 0;
  646.                   l = 1;
  647.                   while (l < v) {
  648.                           r++;
  649.                           l <<= 1;
  650.                   }
  651.  
  652.                   return (r);
  653.           }
  654.  
  655.  
  656.  
  657.                                                                        PPPPaaaaggggeeee 11110000
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  665.  
  666.  
  667.  
  668.           refcnt_t*
  669.           paddr_to_setbase(int node, __uint64_t paddr)
  670.           {
  671.                   int slot_index;
  672.                   int s;
  673.                   uint set_offset;
  674.                   int btoset_shift;
  675.                   refcnt_t* set_base;
  676.  
  677.  
  678.                   btoset_shift = logb2(rcbinfo[node]->rcb_granularity);
  679.                   slot_index = -1;
  680.                   set_offset = 0;
  681.  
  682.                   for (s = 1; s < rcbinfo[node]->rcb_num_slots; s++) {
  683.                           if (paddr < slotconfig[node][s].base) {
  684.                                   slot_index = s - 1;
  685.                                   break;
  686.                           }
  687.                           set_offset += slotconfig[node][s - 1].size >> btoset_shift;
  688.                   }
  689.                   if (slot_index < 0) {
  690.                           fprintf(stderr, "Could not find slot0);
  691.                           exit(1);
  692.                   }
  693.  
  694.                   set_offset += (paddr - slotconfig[node][slot_index].base) >> btoset_shift;
  695.                   set_base  = cbuffer[node] + set_offset * rcbinfo[node]->rcb_sw_counters_per_set;
  696.  
  697.                   return (set_base);
  698.           }
  699.  
  700.  
  701.  
  702.      This function finds the slot where the physical address is located, and
  703.      then calculates and returns the location of the associated set of
  704.      reference counters.
  705.  
  706. EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
  707.    AAAAcccccccceeeessssssssiiiinnnngggg tttthhhheeee RRRReeeeffffeeeerrrreeeennnncccceeee CCCCoooouuuunnnntttteeeerrrrssss vvvviiiiaaaa pppprrrrooooccccffffssss
  708.           /*****************************************************************************
  709.            * Copyright 2000, Silicon Graphics, Inc.
  710.            * ALL RIGHTS RESERVED
  711.            *
  712.            * UNPUBLISHED -- Rights reserved under the copyright laws of the United
  713.            * States.   Use of a copyright notice is precautionary only and does not
  714.            * imply publication or disclosure.
  715.            *
  716.            * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
  717.            * Use, duplication or disclosure by the Government is subject to restrictions
  718.            * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
  719.            * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
  720.  
  721.  
  722.  
  723.                                                                        PPPPaaaaggggeeee 11111111
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  731.  
  732.  
  733.  
  734.            * in similar or successor clauses in the FAR, or the DOD or NASA FAR
  735.            * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
  736.            * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
  737.            *
  738.            * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
  739.            * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
  740.            * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
  741.            * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
  742.            * GRAPHICS, INC.
  743.            ****************************************************************************/
  744.  
  745.  
  746.           #include <stdio.h>
  747.           #include <string.h>
  748.           #include <unistd.h>
  749.           #include <malloc.h>
  750.           #include <sys/types.h>
  751.           #include <sys/mman.h>
  752.           #include <sys/stat.h>
  753.           #include <fcntl.h>
  754.           #include <sys/prctl.h>
  755.           #include <procfs/procfs.h>
  756.           #include <sys/pmo.h>
  757.           #include <sys/syssgi.h>
  758.           #include <sys/sysmp.h>
  759.           #include <sys/SN/hwcntrs.h>
  760.  
  761.           #define HPSIZE           (0x1000)
  762.           #define HPSIZE_MASK      (HPSIZE-1)
  763.           #define HPSIZE_SHIFT     (12)
  764.           #define DATA_POOL_SIZE   (128*1024)
  765.           #define CACHE_TRASH_SIZE ((4*1024*1024)/sizeof(long))
  766.  
  767.           char data_pool[DATA_POOL_SIZE];
  768.           long cache_trash_buffer[CACHE_TRASH_SIZE];
  769.  
  770.  
  771.           void
  772.           place_data(char* vaddr, int size, char* node)
  773.           {
  774.                   pmo_handle_t mld;
  775.                   pmo_handle_t mldset;
  776.                   raff_info_t  rafflist;
  777.                   pmo_handle_t pm;
  778.                   policy_set_t policy_set;
  779.  
  780.                   if ((mld = mld_create(0, size)) < 0) {
  781.                           perror("mld_create");
  782.                           exit(1);
  783.                   }
  784.  
  785.                   if ((mldset = mldset_create(&mld, 1)) < 0) {
  786.  
  787.  
  788.  
  789.                                                                        PPPPaaaaggggeeee 11112222
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  797.  
  798.  
  799.  
  800.                           perror("mldst_create");
  801.                           exit(1);
  802.                   }
  803.  
  804.                   rafflist.resource = node;
  805.                   rafflist.restype = RAFFIDT_NAME;
  806.                   rafflist.reslen = (ushort)strlen(node);
  807.                   rafflist.radius = 0;
  808.                   rafflist.attr = RAFFATTR_ATTRACTION;
  809.  
  810.                   if (mldset_place(mldset,
  811.                                    TOPOLOGY_PHYSNODES,
  812.                                    &rafflist,
  813.                                    1,
  814.                                    RQMODE_ADVISORY) < 0) {
  815.                           perror("mldset_place");
  816.                           exit(1);
  817.                   }
  818.  
  819.                   pm_filldefault(&policy_set);
  820.  
  821.                   policy_set.placement_policy_name = "PlacementFixed";
  822.                   policy_set.placement_policy_args = (void*)mld;
  823.                   policy_set.migration_policy_name = "MigrationRefcnt";
  824.                   policy_set.migration_policy_args = NULL;
  825.  
  826.                   if ((pm = pm_create(&policy_set)) < 0) {
  827.                           perror("pm_create");
  828.                           exit(1);
  829.                   }
  830.  
  831.                   if (pm_attach(pm, vaddr, size) < 0) {
  832.                           perror("pm_attach");
  833.                           exit(1);
  834.                   }
  835.  
  836.           }
  837.  
  838.           void
  839.           place_process(char* node)
  840.           {
  841.                   pmo_handle_t mld;
  842.                   pmo_handle_t mldset;
  843.                   raff_info_t  rafflist;
  844.  
  845.                   /*
  846.                    * The mld, radius = 0 (from one node only)
  847.                    */
  848.  
  849.                   if ((mld = mld_create(0, 0)) < 0) {
  850.                           perror("mld_create");
  851.                           exit(1);
  852.  
  853.  
  854.  
  855.                                                                        PPPPaaaaggggeeee 11113333
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  863.  
  864.  
  865.  
  866.                   }
  867.  
  868.                   /*
  869.                    * The mldset
  870.                    */
  871.  
  872.                   if ((mldset = mldset_create(&mld, 1)) < 0) {
  873.                           perror("mldset_create");
  874.                           exit(1);
  875.                   }
  876.  
  877.                   /*
  878.                    * Placing the mldset with the one mld
  879.                    */
  880.  
  881.                   rafflist.resource = node;
  882.                   rafflist.restype = RAFFIDT_NAME;
  883.                   rafflist.reslen = (ushort)strlen(node);
  884.                   rafflist.radius = 0;
  885.                   rafflist.attr = RAFFATTR_ATTRACTION;
  886.  
  887.                   if (mldset_place(mldset,
  888.                                    TOPOLOGY_PHYSNODES,
  889.                                    &rafflist, 1,
  890.                                    RQMODE_ADVISORY) < 0) {
  891.                           perror("mldset_place");
  892.                           exit(1);
  893.                   }
  894.  
  895.                   /*
  896.                    * Attach this process to run only on the node
  897.                    * where thr mld has been placed.
  898.                    */
  899.  
  900.                   if (process_mldlink(0, mld, RQMODE_MANDATORY) < 0) {
  901.                           perror("process_mldlink");
  902.                           exit(1);
  903.                   }
  904.  
  905.           }
  906.  
  907.  
  908.           void
  909.           print_refcounters(char* vaddr, int len)
  910.           {
  911.                   pid_t pid = getpid();
  912.                   char  pfile[256];
  913.                   int fd;
  914.                   sn0_refcnt_buf_t* refcnt_buffer;
  915.                   sn0_refcnt_buf_t* direct_refcnt_buffer;
  916.                   sn0_refcnt_args_t* refcnt_args;
  917.                   int npages;
  918.  
  919.  
  920.  
  921.                                                                        PPPPaaaaggggeeee 11114444
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  929.  
  930.  
  931.  
  932.                   int numnodes;
  933.                   int page;
  934.                   int node;
  935.  
  936.                   sprintf(pfile, "/proc/%05d", pid);
  937.                   if ((fd = open(pfile, O_RDONLY)) < 0) {
  938.                     fprintf(stderr,"Can't open /proc/%d", pid);
  939.                     exit(1);
  940.                }
  941.  
  942.                   vaddr = (char *)( (unsigned long)vaddr & ~HPSIZE_MASK );
  943.                   npages = (len + HPSIZE_MASK) >> (HPSIZE_SHIFT);
  944.  
  945.                   if ((refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  946.                           perror("malloc refcnt_buffer");
  947.                           exit(1);
  948.                   }
  949.  
  950.                   if ((direct_refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  951.                           perror("malloc refcnt_buffer");
  952.                           exit(1);
  953.                   }
  954.  
  955.                   if ((refcnt_args = malloc(sizeof(sn0_refcnt_args_t))) == NULL) {
  956.                           perror("malloc refcnt_args");
  957.                           exit(1);
  958.                   }
  959.  
  960.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  961.                   refcnt_args->len = len;
  962.                   refcnt_args->buf = refcnt_buffer;
  963.  
  964.                   if (ioctl(fd, PIOCGETSN0EXTREFCNTRS, (void *)refcnt_args) < 0) {
  965.                     perror("ioctl  PIOCGETSN0EXTREFCNTRS returns error");
  966.                     exit(1);
  967.                }
  968.  
  969.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  970.                   refcnt_args->len = len;
  971.                   refcnt_args->buf = direct_refcnt_buffer;
  972.  
  973.                   if (ioctl(fd, PIOCGETSN0REFCNTRS, (void *)refcnt_args) < 0) {
  974.                     perror("ioctl  PIOCGETSN0REFCNTRS returns error");
  975.                     exit(1);
  976.                }
  977.  
  978.                   if ((numnodes = sysmp(MP_NUMNODES)) < 0) {
  979.                           perror("sysmp MP_NUMNODES");
  980.                           exit(1);
  981.                   }
  982.  
  983.                   for (page = 0; page < npages; page++) {
  984.  
  985.  
  986.  
  987.                                                                        PPPPaaaaggggeeee 11115555
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  995.  
  996.  
  997.  
  998.                           printf("page[%05d, 0x%lx, 0x%llx (0x%llx)]:",
  999.                                  page,
  1000.                                  vaddr + page*0x1000,
  1001.                                  refcnt_buffer[page].paddr,
  1002.                                  refcnt_buffer[page].paddr >> 14);
  1003.                           for (node = 0; node < numnodes; node++) {
  1004.                                   printf(" %05lld (%06lld)",
  1005.                                          refcnt_buffer[page].refcnt_set.refcnt[node],
  1006.                                          direct_refcnt_buffer[page].refcnt_set.refcnt[node]);
  1007.                           }
  1008.                           printf("0);
  1009.                   }
  1010.  
  1011.                   close(fd);
  1012.                   free(refcnt_args);
  1013.                   free(refcnt_buffer);
  1014.           }
  1015.  
  1016.  
  1017.           void
  1018.           init_buffer(void* m, size_t size)
  1019.           {
  1020.                   size_t i;
  1021.                   char* p = (char*)m;
  1022.  
  1023.                   for (i = 0; i < size; i++) {
  1024.                           p[i] = (char)i;
  1025.                   }
  1026.           }
  1027.  
  1028.           long
  1029.           buffer_auto_dotproduct_update(void* m, size_t size)
  1030.           {
  1031.                   size_t i;
  1032.                   size_t j;
  1033.                   char* p = (char*)m;
  1034.                   long sum = 0;
  1035.  
  1036.  
  1037.                   for (i = 0, j = size - 1; i < size; i++, j--) {
  1038.                           sum += (long)p[i]-- * (long)p[j]++;
  1039.                   }
  1040.  
  1041.                   return (sum);
  1042.           }
  1043.  
  1044.           long
  1045.           cache_trash(long* m, size_t long_size)
  1046.           {
  1047.                   int i;
  1048.                   long sum = 0;
  1049.  
  1050.  
  1051.  
  1052.  
  1053.                                                                        PPPPaaaaggggeeee 11116666
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1061.  
  1062.  
  1063.  
  1064.                   for (i = 0; i < long_size; i++) {
  1065.                          m[i] = i;
  1066.                   }
  1067.  
  1068.                   for (i = 0; i < long_size; i++) {
  1069.                           sum += m[i];
  1070.                   }
  1071.  
  1072.                   return (sum);
  1073.           }
  1074.  
  1075.           void
  1076.           do_stuff(void* m, size_t size, int loops, char* label)
  1077.           {
  1078.                   int64_t total = 0;
  1079.                   int count = loops;
  1080.  
  1081.                   while (count--) {
  1082.                           total += buffer_auto_dotproduct_update(m, size);
  1083.                           total += cache_trash(cache_trash_buffer, CACHE_TRASH_SIZE);
  1084.                   }
  1085.                   printf("{%s}, sum after %d loops: 0x%llx0, label, loops, total);
  1086.           }
  1087.  
  1088.           void
  1089.           main(int argc, char** argv)
  1090.           {
  1091.                   char* thread_node;
  1092.                   char* mem_node;
  1093.  
  1094.                   if (argc != 3) {
  1095.                           fprintf(stderr, "Usage %s <thread-node> <mem-node>0, argv[0]);
  1096.                           exit(1);
  1097.                   }
  1098.  
  1099.                   thread_node = argv[1];
  1100.                   mem_node = argv[2];
  1101.  
  1102.  
  1103.                   place_data(&data_pool[0], DATA_POOL_SIZE, mem_node);
  1104.                   init_buffer(&data_pool[0], DATA_POOL_SIZE);
  1105.  
  1106.                   /*
  1107.                    * Place process
  1108.                    */
  1109.                   place_process(thread_node);
  1110.  
  1111.                   /*
  1112.                    * Reference pages & print refcnt
  1113.                    */
  1114.  
  1115.                   do_stuff(data_pool, DATA_POOL_SIZE, 100, "BUFFER");
  1116.  
  1117.  
  1118.  
  1119.                                                                        PPPPaaaaggggeeee 11117777
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1127.  
  1128.  
  1129.  
  1130.                   print_refcounters(data_pool, DATA_POOL_SIZE);
  1131.           }
  1132.  
  1133.  
  1134.      The program above places a data buffer and the running process on nodes
  1135.      specified on the command line. When the data buffer is placed, we also
  1136.      enable reference counting by specifying the migration policy to be
  1137.      "MigrationRefcnt". Then we just access the buffer several times, making
  1138.      sure that we flush the cache between loops.  At the end, we print both
  1139.      the extended reference counters and the hardware reference counters for
  1140.      all hardware pages being used for the data buffer.
  1141.  
  1142.      For a machine with the following configuration
  1143.  
  1144.           System Configuration
  1145.           # hinv
  1146.           FPU: MIPS R10010 Floating Point Chip Revision: 0.0
  1147.           CPU: MIPS R10000 Processor Chip Revision: 2.6
  1148.           16 180 MHZ IP27 Processors
  1149.           Main memory size: 2048 Mbytes
  1150.           Instruction cache size: 32 Kbytes
  1151.           Data cache size: 32 Kbytes
  1152.           Secondary unified instruction/data cache size: 1 Mbyte
  1153.  
  1154.           Topology
  1155.  
  1156.           # topology
  1157.  
  1158.           Machine ricotta has 16 cpu's, 8 memory nodes, and 4 routers.
  1159.  
  1160.           The cpus are:
  1161.           cpu   0 is /hw/module/2/slot/n1/node/cpu/a
  1162.           cpu   1 is /hw/module/2/slot/n1/node/cpu/b
  1163.           cpu   2 is /hw/module/2/slot/n2/node/cpu/a
  1164.           cpu   3 is /hw/module/2/slot/n2/node/cpu/b
  1165.           cpu   4 is /hw/module/2/slot/n3/node/cpu/a
  1166.           cpu   5 is /hw/module/2/slot/n3/node/cpu/b
  1167.           cpu   6 is /hw/module/2/slot/n4/node/cpu/a
  1168.           cpu   7 is /hw/module/2/slot/n4/node/cpu/b
  1169.           cpu   8 is /hw/module/1/slot/n1/node/cpu/a
  1170.           cpu   9 is /hw/module/1/slot/n1/node/cpu/b
  1171.           cpu  10 is /hw/module/1/slot/n2/node/cpu/a
  1172.           cpu  11 is /hw/module/1/slot/n2/node/cpu/b
  1173.           cpu  12 is /hw/module/1/slot/n3/node/cpu/a
  1174.           cpu  13 is /hw/module/1/slot/n3/node/cpu/b
  1175.           cpu  14 is /hw/module/1/slot/n4/node/cpu/a
  1176.           cpu  15 is /hw/module/1/slot/n4/node/cpu/b
  1177.  
  1178.           The nodes are:
  1179.           /hw/module/1/slot/n1/node
  1180.           /hw/module/1/slot/n2/node
  1181.           /hw/module/1/slot/n3/node
  1182.  
  1183.  
  1184.  
  1185.                                                                        PPPPaaaaggggeeee 11118888
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1193.  
  1194.  
  1195.  
  1196.           /hw/module/1/slot/n4/node
  1197.           /hw/module/2/slot/n1/node
  1198.           /hw/module/2/slot/n2/node
  1199.           /hw/module/2/slot/n3/node
  1200.           /hw/module/2/slot/n4/node
  1201.  
  1202.           The routers are:
  1203.           /hw/module/1/slot/r1/router
  1204.           /hw/module/1/slot/r2/router
  1205.           /hw/module/2/slot/r1/router
  1206.           /hw/module/2/slot/r2/router
  1207.  
  1208.           The topology is defined by:
  1209.           /hw/module/1/slot/n1/node/link -> /hw/module/1/slot/r1/router
  1210.           /hw/module/1/slot/n2/node/link -> /hw/module/1/slot/r1/router
  1211.           /hw/module/1/slot/n3/node/link -> /hw/module/1/slot/r2/router
  1212.           /hw/module/1/slot/n4/node/link -> /hw/module/1/slot/r2/router
  1213.           /hw/module/2/slot/n1/node/link -> /hw/module/2/slot/r1/router
  1214.           /hw/module/2/slot/n2/node/link -> /hw/module/2/slot/r1/router
  1215.           /hw/module/2/slot/n3/node/link -> /hw/module/2/slot/r2/router
  1216.           /hw/module/2/slot/n4/node/link -> /hw/module/2/slot/r2/router
  1217.  
  1218.           /hw/module/1/slot/r1/router/1 -> /hw/module/2/slot/r1/router
  1219.           /hw/module/1/slot/r1/router/4 -> /hw/module/1/slot/n2/node
  1220.           /hw/module/1/slot/r1/router/5 -> /hw/module/1/slot/n1/node
  1221.           /hw/module/1/slot/r1/router/6 -> /hw/module/1/slot/r2/router
  1222.           /hw/module/1/slot/r2/router/1 -> /hw/module/2/slot/r2/router
  1223.           /hw/module/1/slot/r2/router/4 -> /hw/module/1/slot/n4/node
  1224.           /hw/module/1/slot/r2/router/5 -> /hw/module/1/slot/n3/node
  1225.           /hw/module/1/slot/r2/router/6 -> /hw/module/1/slot/r1/router
  1226.           /hw/module/2/slot/r1/router/1 -> /hw/module/1/slot/r1/router
  1227.           /hw/module/2/slot/r1/router/4 -> /hw/module/2/slot/n2/node
  1228.           /hw/module/2/slot/r1/router/5 -> /hw/module/2/slot/n1/node
  1229.           /hw/module/2/slot/r1/router/6 -> /hw/module/2/slot/r2/router
  1230.           /hw/module/2/slot/r2/router/1 -> /hw/module/1/slot/r2/router
  1231.           /hw/module/2/slot/r2/router/4 -> /hw/module/2/slot/n4/node
  1232.           /hw/module/2/slot/r2/router/5 -> /hw/module/2/slot/n3/node
  1233.           /hw/module/2/slot/r2/router/6 -> /hw/module/2/slot/r1/router
  1234.  
  1235.  
  1236.      we obtain the following output when running the example program:
  1237.  
  1238.           # ./refcnt_procfs /hw/module/2/slot/n3/node /hw/module/2/slot/n3/node
  1239.           {BUFFER}, sum after 100 loops: 0xee780000
  1240.           page[00000, 0x10002000, 0x207ece000 (0x81fb3)]: 00000 (000038) 00000 (000000)
  1241.           00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1242.           page[00001, 0x10003000, 0x207ecf000 (0x81fb3)]: 00000 (000065) 00000 (000000)
  1243.            00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1244.           page[00002, 0x10004000, 0x2278d0000 (0x89e34)]: 00041 (000000) 00000 (000000)
  1245.            01793 (001569) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1246.           page[00003, 0x10005000, 0x2278d1000 (0x89e34)]: 00033 (000000) 00000 (000000)
  1247.            01664 (001504) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1248.  
  1249.  
  1250.  
  1251.                                                                        PPPPaaaaggggeeee 11119999
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1259.  
  1260.  
  1261.  
  1262.           page[00004, 0x10006000, 0x2278d2000 (0x89e34)]: 00032 (000000) 00000 (000000)
  1263.            01664 (001504) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1264.           page[00005, 0x10007000, 0x2278d3000 (0x89e34)]: 00032 (000000) 00000 (000000)
  1265.            01664 (001504) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1266.           page[00006, 0x10008000, 0x207cd4000 (0x81f35)]: 00048 (000000) 00000 (000000)
  1267.            03136 (000032) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1268.           page[00007, 0x10009000, 0x207cd5000 (0x81f35)]: 00039 (000000) 00000 (000000)
  1269.            03586 (000068) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1270.           page[00008, 0x1000a000, 0x207cd6000 (0x81f35)]: 00041 (000000) 00000 (000000)
  1271.            03136 (000065) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1272.           page[00009, 0x1000b000, 0x207cd7000 (0x81f35)]: 00042 (000000) 00000 (000000)
  1273.            03104 (000064) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1274.           page[00010, 0x1000c000, 0x207ad8000 (0x81eb6)]: 00060 (000000) 00000 (000000)
  1275.           01793 (001513) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1276.           page[00011, 0x1000d000, 0x207ad9000 (0x81eb6)]: 00035 (000000) 00000 (000000)
  1277.           01696 (001472) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1278.           page[00012, 0x1000e000, 0x207ada000 (0x81eb6)]: 00032 (000000) 00000 (000000)
  1279.           01696 (001472) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1280.           page[00013, 0x1000f000, 0x207adb000 (0x81eb6)]: 00035 (000000) 00000 (000000)
  1281.            01696 (001472) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1282.           page[00014, 0x10010000, 0x2068dc000 (0x81a37)]: 00041 (000000) 00000 (000000)
  1283.            01793 (001375) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1284.           page[00015, 0x10011000, 0x2068dd000 (0x81a37)]: 00034 (000000) 00000 (000000)
  1285.            01792 (001376) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1286.           page[00016, 0x10012000, 0x2068de000 (0x81a37)]: 00034 (000000) 00000 (000000)
  1287.            01792 (001376) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1288.           page[00017, 0x10013000, 0x2068df000 (0x81a37)]: 00034 (000000) 00000 (000000)
  1289.            01792 (001376) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1290.           page[00018, 0x10014000, 0x206be0000 (0x81af8)]: 00035 (000000) 00000 (000000)
  1291.            01632 (001536) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1292.           page[00019, 0x10015000, 0x206be1000 (0x81af8)]: 00039 (000000) 00000 (000000)
  1293.            01632 (001536) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1294.           page[00020, 0x10016000, 0x206be2000 (0x81af8)]: 00034 (000000) 00000 (000000)
  1295.            01793 (001636) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1296.           page[00021, 0x10017000, 0x206be3000 (0x81af8)]: 00035 (000000) 00000 (000000)
  1297.            01664 (001504) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1298.           page[00022, 0x10018000, 0x226ce4000 (0x89b39)]: 00051 (000000) 00000 (000000)
  1299.            01793 (001515) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1300.           page[00023, 0x10019000, 0x226ce5000 (0x89b39)]: 00044 (000000) 00000 (000000)
  1301.            01728 (001440) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1302.           page[00024, 0x1001a000, 0x226ce6000 (0x89b39)]: 00037 (000000) 00000 (000000)
  1303.            01728 (001440) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1304.           page[00025, 0x1001b000, 0x226ce7000 (0x89b39)]: 00034 (000000) 00000 (000000)
  1305.            01728 (001440) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1306.           page[00026, 0x1001c000, 0x2066e8000 (0x819ba)]: 00033 (000000) 00000 (000000)
  1307.           02741 (000529) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1308.           page[00027, 0x1001d000, 0x2066e9000 (0x819ba)]: 00041 (000000) 00000 (000000)
  1309.            03586 (000680) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1310.           page[00028, 0x1001e000, 0x2066ea000 (0x819ba)]: 00033 (000000) 00000 (000000)
  1311.            02688 (000480) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1312.           page[00029, 0x1001f000, 0x2066eb000 (0x819ba)]: 00034 (000000) 00000 (000000)
  1313.            02688 (000480) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1314.  
  1315.  
  1316.  
  1317.                                                                        PPPPaaaaggggeeee 22220000
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1325.  
  1326.  
  1327.  
  1328.           page[00030, 0x10020000, 0x2200ec000 (0x8803b)]: 00045 (000000) 00000 (000000)
  1329.            02688 (000480) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1330.           page[00031, 0x10021000, 0x2200ed000 (0x8803b)]: 00033 (000000) 00000 (000000)
  1331.            02688 (000480) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  1332.  
  1333.  
  1334.      We place the data buffer and the process on the same node. In this case
  1335.      we chose node /hw/module/2/slot/n3/node, which corresponds to cpus 4 and
  1336.      5 according to the information obtained using the command "topology"
  1337.  
  1338.           cpu   4 is /hw/module/2/slot/n3/node/cpu/a
  1339.           cpu   5 is /hw/module/2/slot/n3/node/cpu/b
  1340.  
  1341.  
  1342.      which corresponds to a node with cnodeid 2.
  1343.  
  1344.      We print one record per hardware page. Each record shows a page number
  1345.      within the data buffer, the virtual address for the page, the physical
  1346.      hardware page associated with the virtual address, and the page frame
  1347.      number for the physical page. Then follows a list of counters, two values
  1348.      per node: the first counter of each pair is the extended reference
  1349.      counter, and the second counter of each pair is the actual hardware
  1350.      reference counter.
  1351.  
  1352.      As expected, we see that the counters for node 2 show a high count.
  1353.  
  1354.    AAAAcccccccceeeessssssssiiiinnnngggg tttthhhheeee eeeexxxxtttteeeennnnddddeeeedddd rrrreeeeffffeeeerrrreeeennnncccceeee ccccoooouuuunnnntttteeeerrrrssss vvvviiiiaaaa mmmmmmmmaaaapppp
  1355.      The following example mmaps the counter buffer, and uses both procfs and
  1356.      the mmapped buffer to access and print out the counts.
  1357.  
  1358.           /*****************************************************************************
  1359.            * Copyright 2000, Silicon Graphics, Inc.
  1360.            * ALL RIGHTS RESERVED
  1361.            *
  1362.            * UNPUBLISHED -- Rights reserved under the copyright laws of the United
  1363.            * States.   Use of a copyright notice is precautionary only and does not
  1364.            * imply publication or disclosure.
  1365.            *
  1366.            * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
  1367.            * Use, duplication or disclosure by the Government is subject to restrictions
  1368.            * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
  1369.            * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
  1370.            * in similar or successor clauses in the FAR, or the DOD or NASA FAR
  1371.            * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
  1372.            * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
  1373.            *
  1374.            * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
  1375.            * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
  1376.            * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
  1377.            * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
  1378.            * GRAPHICS, INC.
  1379.            ****************************************************************************/
  1380.  
  1381.  
  1382.  
  1383.                                                                        PPPPaaaaggggeeee 22221111
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1391.  
  1392.  
  1393.  
  1394.           #include <stdio.h>
  1395.           #include <string.h>
  1396.           #include <unistd.h>
  1397.           #include <malloc.h>
  1398.           #include <sys/types.h>
  1399.           #include <sys/mman.h>
  1400.           #include <sys/stat.h>
  1401.           #include <fcntl.h>
  1402.           #include <sys/prctl.h>
  1403.           #include <procfs/procfs.h>
  1404.           #include <sys/pmo.h>
  1405.           #include <sys/syssgi.h>
  1406.           #include <sys/sysmp.h>
  1407.           #include <sys/SN/hwcntrs.h>
  1408.  
  1409.  
  1410.           #define DATA_POOL_SIZE  (8*16*1024)
  1411.           #define CACHE_TRASH_SIZE ((4*1024*1024)/sizeof(long))
  1412.  
  1413.           char fixed_data_pool[DATA_POOL_SIZE];
  1414.           long cache_trash_buffer[CACHE_TRASH_SIZE];
  1415.  
  1416.           /*
  1417.            * Reference Counter Configuration for all nodes
  1418.            */
  1419.           rcb_info_t** rcbinfo;
  1420.  
  1421.           /*
  1422.            * Hardware Page Size
  1423.            */
  1424.           uint hw_page_size;
  1425.  
  1426.           /*
  1427.            * Physical Memory Config for all nodes
  1428.            */
  1429.           rcb_slot_t** slotconfig;
  1430.  
  1431.           /*
  1432.            * Mapped counters for all nodes
  1433.            */
  1434.           refcnt_t** cbuffer;
  1435.  
  1436.           /*
  1437.            * Verbose ?
  1438.            */
  1439.  
  1440.           int verbose = 0;
  1441.  
  1442.           void
  1443.           print_rcb(int node, rcb_info_t* rcb, rcb_slot_t* slot)
  1444.           {
  1445.                   int s;
  1446.  
  1447.  
  1448.  
  1449.                                                                        PPPPaaaaggggeeee 22222222
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1457.  
  1458.  
  1459.  
  1460.  
  1461.                   printf("RCB for node [%d]0, node);
  1462.  
  1463.                   printf("rcb_len: %lld0, rcb->rcb_len);
  1464.                   printf("rcb_sw_sets: %d0, rcb->rcb_sw_sets);
  1465.                   printf("rcb_sw_counters_per_set: %d0, rcb->rcb_sw_counters_per_set);
  1466.                   printf("rcb_sw_counter_size: %d0, rcb->rcb_sw_counter_size);
  1467.  
  1468.                   printf("rcb_base_pages: %d0, rcb->rcb_base_pages);
  1469.                   printf("rcb_base_page_size: %d0, rcb->rcb_base_page_size);
  1470.                   printf("rcb_base_paddr: 0x%llx0, rcb->rcb_base_paddr);
  1471.  
  1472.                   printf("rcb_cnodeid: %d0, rcb->rcb_cnodeid);
  1473.                   printf("rcb_granularity: %d0, rcb->rcb_granularity);
  1474.                   printf("rcb_hw_counter_max: %d0, rcb->rcb_hw_counter_max);
  1475.                   printf("rcb_diff_threshold: %d0, rcb->rcb_diff_threshold);
  1476.                   printf("rcb_abs_threshold: %d0, rcb->rcb_abs_threshold);
  1477.  
  1478.                   for (s = 0; s < rcb->rcb_num_slots; s++) {
  1479.                           printf("Slot[%d]: 0x%llx -> 0x%llx, size: 0x%llx0,
  1480.                                  s, slot[s].base, slot[s].base + slot[s].size, slot[s].size);
  1481.                   }
  1482.           }
  1483.  
  1484.           void
  1485.           mmap_counters(void)
  1486.           {
  1487.                   int fd;
  1488.                   char refcnt[1024];
  1489.                   refcnt_t* set_base;
  1490.                   int numnodes;
  1491.                   int node;
  1492.  
  1493.                   /* number of nodes */
  1494.  
  1495.                   numnodes = sysmp(MP_NUMNODES);
  1496.  
  1497.                   /* space for refcnt config -- just basic array for now */
  1498.  
  1499.                   rcbinfo = (rcb_info_t**)malloc(sizeof(rcb_info_t*) * numnodes);
  1500.                   if (rcbinfo == NULL) {
  1501.                           perror("malloc");
  1502.                           exit(1);
  1503.                   }
  1504.  
  1505.                   /* space for phys mem config -- just basic array for now*/
  1506.  
  1507.                   slotconfig = (rcb_slot_t**)malloc(sizeof(rcb_slot_t*) * numnodes);
  1508.                   if (slotconfig == NULL) {
  1509.                           perror("malloc");
  1510.                           exit(1);
  1511.                   }
  1512.  
  1513.  
  1514.  
  1515.                                                                        PPPPaaaaggggeeee 22223333
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1523.  
  1524.  
  1525.  
  1526.                   /* space for array of pointers to the counter buffers */
  1527.                   cbuffer = (refcnt_t**)malloc(sizeof(refcnt_t*) * numnodes);
  1528.                   if (cbuffer == NULL) {
  1529.                           perror("malloc");
  1530.                           exit(1);
  1531.                   }
  1532.  
  1533.                   for (node = 0; node < numnodes; node++) {
  1534.                           sprintf(refcnt, "/hw/nodenum/%d/refcnt", node);
  1535.                           if (verbose) {
  1536.                                   printf("Opening dev %s0, refcnt);
  1537.                           }
  1538.  
  1539.                           if ((fd = open(refcnt, O_RDONLY)) < 0) {
  1540.                                   perror("open");
  1541.                                   exit(1);
  1542.                           }
  1543.  
  1544.                           /* get rcb info */
  1545.  
  1546.                           rcbinfo[node] = (rcb_info_t*)malloc(sizeof(rcb_info_t));
  1547.                           if (rcbinfo[node] == NULL) {
  1548.                                   perror("malloc");
  1549.                                   exit(1);
  1550.                           }
  1551.  
  1552.                           if (ioctl(fd, RCB_INFO_GET, rcbinfo[node]) < 0) {
  1553.                                   perror("icctl RCB_INFO_GET");
  1554.                                   exit(1);
  1555.                           }
  1556.  
  1557.                           /* get phys mem config */
  1558.  
  1559.                           slotconfig[node] = (rcb_slot_t*)malloc(rcbinfo[node]->rcb_num_slots *
  1560.                                               sizeof(rcb_slot_t));
  1561.                           if (slotconfig[node] == NULL) {
  1562.                                   perror("malloc");
  1563.                                   exit(1);
  1564.                           }
  1565.  
  1566.                           if (ioctl(fd, RCB_SLOT_GET, slotconfig[node]) < 0) {
  1567.                                   perror("ioctl RCB_SLOT_GET");
  1568.                                   exit(1);
  1569.                           }
  1570.  
  1571.                           /* map the counter buffer for this node */
  1572.                           cbuffer[node] = (refcnt_t*)mmap(0, rcbinfo[node]->rcb_len,
  1573.                                                           PROT_READ, MAP_SHARED, fd, 0);
  1574.                           if (cbuffer[node] == (refcnt_t*)MAP_FAILED) {
  1575.                                   perror("mmap");
  1576.                                   exit(1);
  1577.                           }
  1578.  
  1579.  
  1580.  
  1581.                                                                        PPPPaaaaggggeeee 22224444
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1589.  
  1590.  
  1591.  
  1592.                           if (verbose) {
  1593.                                   print_rcb(node, rcbinfo[node], slotconfig[node]);
  1594.                           }
  1595.  
  1596.                           if (close(fd) <  0) {
  1597.                                   perror("close");
  1598.                                   exit(1);
  1599.                           }
  1600.  
  1601.                   }
  1602.           }
  1603.  
  1604.  
  1605.           uint
  1606.           logb2(uint v)
  1607.           {
  1608.                   uint r;
  1609.                   uint l;
  1610.  
  1611.                   r = 0;
  1612.                   l = 1;
  1613.                   while (l < v) {
  1614.                           r++;
  1615.                           l <<= 1;
  1616.                   }
  1617.  
  1618.                   return (r);
  1619.           }
  1620.  
  1621.  
  1622.           refcnt_t*
  1623.           paddr_to_setbase(int node, __uint64_t paddr)
  1624.           {
  1625.                   int slot_index;
  1626.                   int s;
  1627.                   uint set_offset;
  1628.                   int btoset_shift;
  1629.                   refcnt_t* set_base;
  1630.  
  1631.  
  1632.                   btoset_shift = logb2(rcbinfo[node]->rcb_granularity);
  1633.                   slot_index = -1;
  1634.                   set_offset = 0;
  1635.  
  1636.                   for (s = 1; s < rcbinfo[node]->rcb_num_slots; s++) {
  1637.                           if (paddr < slotconfig[node][s].base) {
  1638.                                   slot_index = s - 1;
  1639.                                   break;
  1640.                           }
  1641.                           set_offset += slotconfig[node][s - 1].size >> btoset_shift;
  1642.                   }
  1643.                   if (slot_index < 0) {
  1644.  
  1645.  
  1646.  
  1647.                                                                        PPPPaaaaggggeeee 22225555
  1648.  
  1649.  
  1650.  
  1651.  
  1652.  
  1653.  
  1654. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1655.  
  1656.  
  1657.  
  1658.                           fprintf(stderr, "Could not find slot0);
  1659.                           exit(1);
  1660.                   }
  1661.  
  1662.                   set_offset += (paddr - slotconfig[node][slot_index].base) >> btoset_shift;
  1663.                   set_base  = cbuffer[node] + set_offset * rcbinfo[node]->rcb_sw_counters_per_set;
  1664.  
  1665.                   return (set_base);
  1666.           }
  1667.  
  1668.           void
  1669.           place_data(char* vaddr, int size, char* node, int migr_on)
  1670.           {
  1671.                   pmo_handle_t mld;
  1672.                   pmo_handle_t mldset;
  1673.                   raff_info_t  rafflist;
  1674.                   pmo_handle_t pm;
  1675.                   policy_set_t policy_set;
  1676.                   migr_policy_uparms_t migr_parms;
  1677.  
  1678.                   if ((mld = mld_create(0, size)) < 0) {
  1679.                           perror("mld_create");
  1680.                           exit(1);
  1681.                   }
  1682.  
  1683.                   if ((mldset = mldset_create(&mld, 1)) < 0) {
  1684.                           perror("mldst_create");
  1685.                           exit(1);
  1686.                   }
  1687.  
  1688.                   rafflist.resource = node;
  1689.                   rafflist.restype = RAFFIDT_NAME;
  1690.                   rafflist.reslen = (ushort)strlen(node);
  1691.                   rafflist.radius = 0;
  1692.                   rafflist.attr = RAFFATTR_ATTRACTION;
  1693.  
  1694.                   if (mldset_place(mldset,
  1695.                                    TOPOLOGY_PHYSNODES,
  1696.                                    &rafflist,
  1697.                                    1,
  1698.                                    RQMODE_ADVISORY) < 0) {
  1699.                           perror("mldset_place");
  1700.                           exit(1);
  1701.                   }
  1702.  
  1703.                   pm_filldefault(&policy_set);
  1704.  
  1705.                   policy_set.placement_policy_name = "PlacementFixed";
  1706.                   policy_set.placement_policy_args = (void*)mld;
  1707.                   policy_set.migration_policy_name = "MigrationRefcnt";
  1708.                   policy_set.migration_policy_args = NULL;
  1709.  
  1710.  
  1711.  
  1712.  
  1713.                                                                        PPPPaaaaggggeeee 22226666
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1721.  
  1722.  
  1723.  
  1724.                   if ((pm = pm_create(&policy_set)) < 0) {
  1725.                           perror("pm_create");
  1726.                           exit(1);
  1727.                   }
  1728.  
  1729.                   if (pm_attach(pm, vaddr, size) < 0) {
  1730.                           perror("pm_attach");
  1731.                           exit(1);
  1732.                   }
  1733.  
  1734.           }
  1735.  
  1736.           void
  1737.           place_process(char* node)
  1738.           {
  1739.                   pmo_handle_t mld;
  1740.                   pmo_handle_t mldset;
  1741.                   raff_info_t  rafflist;
  1742.  
  1743.                   /*
  1744.                    * The mld, radius = 0 (from one node only)
  1745.                    */
  1746.  
  1747.                   if ((mld = mld_create(0, 0)) < 0) {
  1748.                           perror("mld_create");
  1749.                           exit(1);
  1750.                   }
  1751.  
  1752.                   /*
  1753.                    * The mldset
  1754.                    */
  1755.  
  1756.                   if ((mldset = mldset_create(&mld, 1)) < 0) {
  1757.                           perror("mldset_create");
  1758.                           exit(1);
  1759.                   }
  1760.  
  1761.                   /*
  1762.                    * Placing the mldset with the one mld
  1763.                    */
  1764.  
  1765.                   rafflist.resource = node;
  1766.                   rafflist.restype = RAFFIDT_NAME;
  1767.                   rafflist.reslen = (ushort)strlen(node);
  1768.                   rafflist.radius = 0;
  1769.                   rafflist.attr = RAFFATTR_ATTRACTION;
  1770.  
  1771.                   if (mldset_place(mldset,
  1772.                                    TOPOLOGY_PHYSNODES,
  1773.                                    &rafflist, 1,
  1774.                                    RQMODE_ADVISORY) < 0) {
  1775.                           perror("mldset_place");
  1776.  
  1777.  
  1778.  
  1779.                                                                        PPPPaaaaggggeeee 22227777
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.  
  1786. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1787.  
  1788.  
  1789.  
  1790.                           exit(1);
  1791.                   }
  1792.  
  1793.                   /*
  1794.                    * Attach this process to run only on the node
  1795.                    * where thr mld has been placed.
  1796.                    */
  1797.  
  1798.                   if (process_mldlink(0, mld, RQMODE_MANDATORY) < 0) {
  1799.                           perror("process_mldlink");
  1800.                           exit(1);
  1801.                   }
  1802.  
  1803.           }
  1804.  
  1805.  
  1806.           void
  1807.           print_refcounters(char* vaddr, int len)
  1808.           {
  1809.                   pid_t pid = getpid();
  1810.                   char  pfile[256];
  1811.                   int fd;
  1812.                   sn0_refcnt_buf_t* refcnt_buffer;
  1813.                   sn0_refcnt_buf_t* direct_refcnt_buffer;
  1814.                   sn0_refcnt_args_t* refcnt_args;
  1815.                   int npages;
  1816.                   int gen_start;
  1817.                   int numnodes;
  1818.                   int page;
  1819.                   int node;
  1820.                   char mem_node[512];
  1821.                   refcnt_t* set_base;
  1822.  
  1823.                   sprintf(pfile, "/proc/%05d", pid);
  1824.                   if ((fd = open(pfile, O_RDONLY)) < 0) {
  1825.                     fprintf(stderr,"Can't open /proc/%d", pid);
  1826.                     exit(1);
  1827.                }
  1828.  
  1829.                   vaddr = (char *)( (unsigned long)vaddr & ~(hw_page_size-1) );
  1830.                   npages = (len + (hw_page_size-1)) >> logb2(hw_page_size);
  1831.  
  1832.                   if ((refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  1833.                           perror("malloc refcnt_buffer");
  1834.                           exit(1);
  1835.                   }
  1836.  
  1837.                   if ((direct_refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  1838.                           perror("malloc refcnt_buffer");
  1839.                           exit(1);
  1840.                   }
  1841.  
  1842.  
  1843.  
  1844.  
  1845.                                                                        PPPPaaaaggggeeee 22228888
  1846.  
  1847.  
  1848.  
  1849.  
  1850.  
  1851.  
  1852. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1853.  
  1854.  
  1855.  
  1856.                   if ((refcnt_args = malloc(sizeof(sn0_refcnt_args_t))) == NULL) {
  1857.                           perror("malloc refcnt_args");
  1858.                           exit(1);
  1859.                   }
  1860.  
  1861.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  1862.                   refcnt_args->len = len;
  1863.                   refcnt_args->buf = refcnt_buffer;
  1864.  
  1865.                   if ((gen_start = ioctl(fd, PIOCGETSN0EXTREFCNTRS, (void *)refcnt_args)) < 0) {
  1866.                     perror("ioctl  PIOCGETSN0EXTREFCNTRS returns error");
  1867.                     exit(1);
  1868.                }
  1869.  
  1870.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  1871.                   refcnt_args->len = len;
  1872.                   refcnt_args->buf = direct_refcnt_buffer;
  1873.                   if ((gen_start = ioctl(fd, PIOCGETSN0REFCNTRS, (void *)refcnt_args)) < 0) {
  1874.                     perror("ioctl  PIOCGETSN0REFCNTRS returns error");
  1875.                     exit(1);
  1876.                }
  1877.  
  1878.                   if ((numnodes = sysmp(MP_NUMNODES)) < 0) {
  1879.                           perror("sysmp MP_NUMNODES");
  1880.                           exit(1);
  1881.                   }
  1882.  
  1883.                   for (page = 0; page < npages; page++) {
  1884.                           printf("page[%05d, 0x%lx, 0x%llx (0x%llx)]:",
  1885.                                  page,
  1886.                                  vaddr + page*0x1000,
  1887.                                  refcnt_buffer[page].paddr,
  1888.                                  refcnt_buffer[page].paddr >> 14);
  1889.                           for (node = 0; node < numnodes; node++) {
  1890.                                   printf(" %05llu (%06llu)",
  1891.                                          refcnt_buffer[page].refcnt_set.refcnt[node],
  1892.                                          direct_refcnt_buffer[page].refcnt_set.refcnt[node]);
  1893.                           }
  1894.                           printf("0);
  1895.  
  1896.                           set_base = paddr_to_setbase(refcnt_buffer[page].cnodeid,
  1897.                                                       refcnt_buffer[page].paddr);
  1898.                           printf("MMAPPED CTRS: ");
  1899.                           for (node = 0; node < numnodes; node++) {
  1900.                                   printf(" %05llu (%06llu)",
  1901.                                          set_base[node],
  1902.                                          direct_refcnt_buffer[page].refcnt_set.refcnt[node]);
  1903.                           }
  1904.                           printf("0);
  1905.                   }
  1906.  
  1907.                   close(fd);
  1908.  
  1909.  
  1910.  
  1911.                                                                        PPPPaaaaggggeeee 22229999
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1919.  
  1920.  
  1921.  
  1922.                   free(refcnt_args);
  1923.                   free(refcnt_buffer);
  1924.           }
  1925.  
  1926.           void
  1927.           check_refcounters(char* vaddr, int len)
  1928.           {
  1929.                   pid_t pid = getpid();
  1930.                   char  pfile[256];
  1931.                   int fd;
  1932.                   sn0_refcnt_buf_t* refcnt_buffer;
  1933.                   sn0_refcnt_buf_t* direct_refcnt_buffer;
  1934.                   sn0_refcnt_args_t* refcnt_args;
  1935.                   int npages;
  1936.                   int gen_start;
  1937.                   int numnodes;
  1938.                   int page;
  1939.                   int node;
  1940.                   char mem_node[512];
  1941.                   refcnt_t* set_base;
  1942.  
  1943.                   sprintf(pfile, "/proc/%05d", pid);
  1944.                   if ((fd = open(pfile, O_RDONLY)) < 0) {
  1945.                     fprintf(stderr,"Can't open /proc/%d", pid);
  1946.                     exit(1);
  1947.                }
  1948.  
  1949.                   vaddr = (char *)( (unsigned long)vaddr & ~0xfff );
  1950.                   npages = (len + 0xfff) >> 12;
  1951.  
  1952.                   if ((refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  1953.                           perror("malloc refcnt_buffer");
  1954.                           exit(1);
  1955.                   }
  1956.  
  1957.                   if ((direct_refcnt_buffer = malloc(sizeof(sn0_refcnt_buf_t) * npages)) == NULL) {
  1958.                           perror("malloc refcnt_buffer");
  1959.                           exit(1);
  1960.                   }
  1961.  
  1962.                   if ((refcnt_args = malloc(sizeof(sn0_refcnt_args_t))) == NULL) {
  1963.                           perror("malloc refcnt_args");
  1964.                           exit(1);
  1965.                   }
  1966.  
  1967.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  1968.                   refcnt_args->len = len;
  1969.                   refcnt_args->buf = refcnt_buffer;
  1970.  
  1971.                   if ((gen_start = ioctl(fd, PIOCGETSN0EXTREFCNTRS, (void *)refcnt_args)) < 0) {
  1972.                     perror("ioctl  PIOCGETSN0EXTREFCNTRS returns error");
  1973.                     exit(1);
  1974.  
  1975.  
  1976.  
  1977.                                                                        PPPPaaaaggggeeee 33330000
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  1985.  
  1986.  
  1987.  
  1988.               }
  1989.  
  1990.                   refcnt_args->vaddr = (__uint64_t)vaddr;
  1991.                   refcnt_args->len = len;
  1992.                   refcnt_args->buf = direct_refcnt_buffer;
  1993.                   if ((gen_start = ioctl(fd, PIOCGETSN0REFCNTRS, (void *)refcnt_args)) < 0) {
  1994.                     perror("ioctl  PIOCGETSN0REFCNTRS returns error");
  1995.                     exit(1);
  1996.                }
  1997.  
  1998.                   if ((numnodes = sysmp(MP_NUMNODES)) < 0) {
  1999.                           perror("sysmp MP_NUMNODES");
  2000.                           exit(1);
  2001.                   }
  2002.  
  2003.                   for (page = 0; page < npages; page++) {
  2004.                           set_base = paddr_to_setbase(refcnt_buffer[page].cnodeid,
  2005.                                                       refcnt_buffer[page].paddr);
  2006.                           for (node = 0; node < numnodes; node++) {
  2007.                                   if (refcnt_buffer[page].refcnt_set.refcnt[node] !=
  2008.                                       set_base[node]) {
  2009.                                           if (verbose) {
  2010.                                                fprintf(stderr,
  2011.                                                "DIFF: procf-refcnt: %lld, mmapped-refcnt: %lld0,
  2012.                                                refcnt_buffer[page].refcnt_set.refcnt[node],
  2013.                                                set_base[node]);
  2014.                                           }
  2015.                                   }
  2016.                           }
  2017.                   }
  2018.  
  2019.                   close(fd);
  2020.                   free(refcnt_args);
  2021.                   free(refcnt_buffer);
  2022.           }
  2023.  
  2024.  
  2025.  
  2026.           void
  2027.           init_buffer(void* m, size_t size)
  2028.           {
  2029.                   size_t i;
  2030.                   char* p = (char*)m;
  2031.  
  2032.                   for (i = 0; i < size; i++) {
  2033.                           p[i] = (char)i;
  2034.                   }
  2035.           }
  2036.  
  2037.           long
  2038.           buffer_auto_dotproduct_update(void* m, size_t size)
  2039.           {
  2040.  
  2041.  
  2042.  
  2043.                                                                        PPPPaaaaggggeeee 33331111
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2051.  
  2052.  
  2053.  
  2054.                   size_t i;
  2055.                   size_t j;
  2056.                   char* p = (char*)m;
  2057.                   long sum = 0;
  2058.  
  2059.  
  2060.                   for (i = 0, j = size - 1; i < size; i++, j--) {
  2061.                           sum += (long)p[i]-- * (long)p[j]++;
  2062.                   }
  2063.  
  2064.                   return (sum);
  2065.           }
  2066.  
  2067.           long
  2068.           cache_trash(long* m, size_t long_size)
  2069.           {
  2070.                   int i;
  2071.                   long sum = 0;
  2072.  
  2073.                   for (i = 0; i < long_size; i++) {
  2074.                          m[i] = i;
  2075.                   }
  2076.  
  2077.                   for (i = 0; i < long_size; i++) {
  2078.                           sum += m[i];
  2079.                   }
  2080.  
  2081.                   return (sum);
  2082.           }
  2083.  
  2084.  
  2085.  
  2086.           void
  2087.           do_stuff(void* m, size_t size, int loops, char* label)
  2088.           {
  2089.                   int64_t total = 0;
  2090.                   int count = loops;
  2091.  
  2092.                   while (count--) {
  2093.                           total += buffer_auto_dotproduct_update(m, size);
  2094.                           total += cache_trash(cache_trash_buffer, CACHE_TRASH_SIZE);
  2095.                   }
  2096.  
  2097.                   if (verbose) {
  2098.                           printf("{%s}, sum after %d loops: 0x%llx0, label, loops, total);
  2099.                   }
  2100.           }
  2101.  
  2102.  
  2103.  
  2104.           void
  2105.           main(int argc, char** argv)
  2106.  
  2107.  
  2108.  
  2109.                                                                        PPPPaaaaggggeeee 33332222
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2117.  
  2118.  
  2119.  
  2120.           {
  2121.                   char* thread_node;
  2122.                   char* mem_node;
  2123.  
  2124.                   if (argc != 4) {
  2125.                           fprintf(stderr,
  2126.                           "Usage %s <thread-node> <mem-node> <0|1 (verbose)>0, argv[0]);
  2127.                           exit(1);
  2128.                   }
  2129.  
  2130.                   thread_node = argv[1];
  2131.                   mem_node = argv[2];
  2132.                   verbose = atoi(argv[3]);
  2133.  
  2134.                   mmap_counters();
  2135.                   hw_page_size = rcbinfo[0]->rcb_granularity;
  2136.  
  2137.                   /*
  2138.                    * Place data, migr off
  2139.                    */
  2140.                   place_data(&fixed_data_pool[0], DATA_POOL_SIZE, mem_node, 0);
  2141.                   init_buffer(&fixed_data_pool[0], DATA_POOL_SIZE);
  2142.  
  2143.                   /*
  2144.                    * Place process
  2145.                    */
  2146.                   place_process(thread_node);
  2147.  
  2148.  
  2149.                   /*
  2150.                    * Reference pages & verify
  2151.                    */
  2152.  
  2153.                   do_stuff(fixed_data_pool, DATA_POOL_SIZE, 100, "FIXED");
  2154.  
  2155.                   if (verbose) {
  2156.                           print_refcounters(fixed_data_pool, DATA_POOL_SIZE);
  2157.                   }
  2158.  
  2159.                   check_refcounters(fixed_data_pool, DATA_POOL_SIZE);
  2160.  
  2161.  
  2162.  
  2163.           }
  2164.  
  2165.  
  2166.  
  2167.      The output on ricotta follows:
  2168.  
  2169.           ricotta:migr> mapcnt /hw/nodenum/3 /hw/nodenum/3  1
  2170.           Opening dev /hw/nodenum/0/refcnt
  2171.           RCB for node [0]
  2172.  
  2173.  
  2174.  
  2175.                                                                        PPPPaaaaggggeeee 33333333
  2176.  
  2177.  
  2178.  
  2179.  
  2180.  
  2181.  
  2182. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2183.  
  2184.  
  2185.  
  2186.                   rcb_len: 4194304
  2187.                   rcb_sw_sets: 65536
  2188.                   rcb_sw_counters_per_set: 8
  2189.                   rcb_sw_counter_size: 8
  2190.                   rcb_base_pages: 16384
  2191.                   rcb_base_page_size: 16384
  2192.                   rcb_base_paddr: 0x800000000
  2193.                   rcb_cnodeid: 0
  2194.                   rcb_granularity: 4096
  2195.                   rcb_hw_counter_max: 2047
  2196.                   rcb_diff_threshold: 10
  2197.                   rcb_abs_threshold: 1023
  2198.                   Slot[0]: 0x800000000 -> 0x808000000, size: 0x8000000
  2199.                   Slot[1]: 0x820000000 -> 0x828000000, size: 0x8000000
  2200.                   Slot[2]: 0x840000000 -> 0x840000000, size: 0x0
  2201.                   Slot[3]: 0x860000000 -> 0x860000000, size: 0x0
  2202.                   Slot[4]: 0x880000000 -> 0x880000000, size: 0x0
  2203.                   Slot[5]: 0x8a0000000 -> 0x8a0000000, size: 0x0
  2204.                   Slot[6]: 0x8c0000000 -> 0x8c0000000, size: 0x0
  2205.                   Slot[7]: 0x8e0000000 -> 0x8e0000000, size: 0x0
  2206.           Opening dev /hw/nodenum/1/refcnt
  2207.           RCB for node [1]
  2208.                   rcb_len: 4194304
  2209.                   rcb_sw_sets: 65536
  2210.                   rcb_sw_counters_per_set: 8
  2211.                   rcb_sw_counter_size: 8
  2212.                   rcb_base_pages: 16384
  2213.                   rcb_base_page_size: 16384
  2214.                   rcb_base_paddr: 0x900000000
  2215.                   rcb_cnodeid: 1
  2216.                   rcb_granularity: 4096
  2217.                   rcb_hw_counter_max: 2047
  2218.                   rcb_diff_threshold: 10
  2219.                   rcb_abs_threshold: 1023
  2220.                   Slot[0]: 0x900000000 -> 0x908000000, size: 0x8000000
  2221.                   Slot[1]: 0x920000000 -> 0x928000000, size: 0x8000000
  2222.                   Slot[2]: 0x940000000 -> 0x940000000, size: 0x0
  2223.                   Slot[3]: 0x960000000 -> 0x960000000, size: 0x0
  2224.                   Slot[4]: 0x980000000 -> 0x980000000, size: 0x0
  2225.                   Slot[5]: 0x9a0000000 -> 0x9a0000000, size: 0x0
  2226.                   Slot[6]: 0x9c0000000 -> 0x9c0000000, size: 0x0
  2227.                   Slot[7]: 0x9e0000000 -> 0x9e0000000, size: 0x0
  2228.           Opening dev /hw/nodenum/2/refcnt
  2229.           RCB for node [2]
  2230.                   rcb_len: 4194304
  2231.                   rcb_sw_sets: 65536
  2232.                   rcb_sw_counters_per_set: 8
  2233.                   rcb_sw_counter_size: 8
  2234.                   rcb_base_pages: 16384
  2235.                   rcb_base_page_size: 16384
  2236.                   rcb_base_paddr: 0xa00000000
  2237.                   rcb_cnodeid: 2
  2238.  
  2239.  
  2240.  
  2241.                                                                        PPPPaaaaggggeeee 33334444
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2249.  
  2250.  
  2251.  
  2252.                   rcb_granularity: 4096
  2253.                   rcb_hw_counter_max: 2047
  2254.                   rcb_diff_threshold: 10
  2255.                   rcb_abs_threshold: 1023
  2256.                   Slot[0]: 0xa00000000 -> 0xa08000000, size: 0x8000000
  2257.                   Slot[1]: 0xa20000000 -> 0xa28000000, size: 0x8000000
  2258.                   Slot[2]: 0xa40000000 -> 0xa40000000, size: 0x0
  2259.                   Slot[3]: 0xa60000000 -> 0xa60000000, size: 0x0
  2260.                   Slot[4]: 0xa80000000 -> 0xa80000000, size: 0x0
  2261.                   Slot[5]: 0xaa0000000 -> 0xaa0000000, size: 0x0
  2262.                   Slot[6]: 0xac0000000 -> 0xac0000000, size: 0x0
  2263.                   Slot[7]: 0xae0000000 -> 0xae0000000, size: 0x0
  2264.           Opening dev /hw/nodenum/3/refcnt
  2265.           RCB for node [3]
  2266.                   rcb_len: 4194304
  2267.                   rcb_sw_sets: 65536
  2268.                   rcb_sw_counters_per_set: 8
  2269.                   rcb_sw_counter_size: 8
  2270.                   rcb_base_pages: 16384
  2271.                   rcb_base_page_size: 16384
  2272.                   rcb_base_paddr: 0xb00000000
  2273.                   rcb_cnodeid: 3
  2274.                   rcb_granularity: 4096
  2275.                   rcb_hw_counter_max: 2047
  2276.                   rcb_diff_threshold: 10
  2277.                   rcb_abs_threshold: 1023
  2278.                   Slot[0]: 0xb00000000 -> 0xb08000000, size: 0x8000000
  2279.                   Slot[1]: 0xb20000000 -> 0xb28000000, size: 0x8000000
  2280.                   Slot[2]: 0xb40000000 -> 0xb40000000, size: 0x0
  2281.                   Slot[3]: 0xb60000000 -> 0xb60000000, size: 0x0
  2282.                   Slot[4]: 0xb80000000 -> 0xb80000000, size: 0x0
  2283.                   Slot[5]: 0xba0000000 -> 0xba0000000, size: 0x0
  2284.                   Slot[6]: 0xbc0000000 -> 0xbc0000000, size: 0x0
  2285.                   Slot[7]: 0xbe0000000 -> 0xbe0000000, size: 0x0
  2286.           Opening dev /hw/nodenum/4/refcnt
  2287.           RCB for node [4]
  2288.                   rcb_len: 4194304
  2289.                   rcb_sw_sets: 65536
  2290.                   rcb_sw_counters_per_set: 8
  2291.                   rcb_sw_counter_size: 8
  2292.                   rcb_base_pages: 16384
  2293.                   rcb_base_page_size: 16384
  2294.                   rcb_base_paddr: 0xc00000000
  2295.                   rcb_cnodeid: 4
  2296.                   rcb_granularity: 4096
  2297.                   rcb_hw_counter_max: 2047
  2298.                   rcb_diff_threshold: 10
  2299.                   rcb_abs_threshold: 1023
  2300.                   Slot[0]: 0xc00000000 -> 0xc08000000, size: 0x8000000
  2301.                   Slot[1]: 0xc20000000 -> 0xc28000000, size: 0x8000000
  2302.                   Slot[2]: 0xc40000000 -> 0xc40000000, size: 0x0
  2303.                   Slot[3]: 0xc60000000 -> 0xc60000000, size: 0x0
  2304.  
  2305.  
  2306.  
  2307.                                                                        PPPPaaaaggggeeee 33335555
  2308.  
  2309.  
  2310.  
  2311.  
  2312.  
  2313.  
  2314. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2315.  
  2316.  
  2317.  
  2318.                   Slot[4]: 0xc80000000 -> 0xc80000000, size: 0x0
  2319.                   Slot[5]: 0xca0000000 -> 0xca0000000, size: 0x0
  2320.                   Slot[6]: 0xcc0000000 -> 0xcc0000000, size: 0x0
  2321.                   Slot[7]: 0xce0000000 -> 0xce0000000, size: 0x0
  2322.           Opening dev /hw/nodenum/5/refcnt
  2323.           RCB for node [5]
  2324.                   rcb_len: 4194304
  2325.                   rcb_sw_sets: 65536
  2326.                   rcb_sw_counters_per_set: 8
  2327.                   rcb_sw_counter_size: 8
  2328.                   rcb_base_pages: 16384
  2329.                   rcb_base_page_size: 16384
  2330.                   rcb_base_paddr: 0xd00000000
  2331.                   rcb_cnodeid: 5
  2332.                   rcb_granularity: 4096
  2333.                   rcb_hw_counter_max: 2047
  2334.                   rcb_diff_threshold: 10
  2335.                   rcb_abs_threshold: 1023
  2336.                   Slot[0]: 0xd00000000 -> 0xd08000000, size: 0x8000000
  2337.                   Slot[1]: 0xd20000000 -> 0xd28000000, size: 0x8000000
  2338.                   Slot[2]: 0xd40000000 -> 0xd40000000, size: 0x0
  2339.                   Slot[3]: 0xd60000000 -> 0xd60000000, size: 0x0
  2340.                   Slot[4]: 0xd80000000 -> 0xd80000000, size: 0x0
  2341.                   Slot[5]: 0xda0000000 -> 0xda0000000, size: 0x0
  2342.                   Slot[6]: 0xdc0000000 -> 0xdc0000000, size: 0x0
  2343.                   Slot[7]: 0xde0000000 -> 0xde0000000, size: 0x0
  2344.           Opening dev /hw/nodenum/6/refcnt
  2345.           RCB for node [6]
  2346.                   rcb_len: 4194304
  2347.                   rcb_sw_sets: 65536
  2348.                   rcb_sw_counters_per_set: 8
  2349.                   rcb_sw_counter_size: 8
  2350.                   rcb_base_pages: 16384
  2351.                   rcb_base_page_size: 16384
  2352.                   rcb_base_paddr: 0xe00000000
  2353.                   rcb_cnodeid: 6
  2354.                   rcb_granularity: 4096
  2355.                   rcb_hw_counter_max: 2047
  2356.                   rcb_diff_threshold: 10
  2357.                   rcb_abs_threshold: 1023
  2358.                   Slot[0]: 0xe00000000 -> 0xe08000000, size: 0x8000000
  2359.                   Slot[1]: 0xe20000000 -> 0xe28000000, size: 0x8000000
  2360.                   Slot[2]: 0xe40000000 -> 0xe40000000, size: 0x0
  2361.                   Slot[3]: 0xe60000000 -> 0xe60000000, size: 0x0
  2362.                   Slot[4]: 0xe80000000 -> 0xe80000000, size: 0x0
  2363.                   Slot[5]: 0xea0000000 -> 0xea0000000, size: 0x0
  2364.                   Slot[6]: 0xec0000000 -> 0xec0000000, size: 0x0
  2365.                   Slot[7]: 0xee0000000 -> 0xee0000000, size: 0x0
  2366.           Opening dev /hw/nodenum/7/refcnt
  2367.           RCB for node [7]
  2368.                   rcb_len: 4194304
  2369.                   rcb_sw_sets: 65536
  2370.  
  2371.  
  2372.  
  2373.                                                                        PPPPaaaaggggeeee 33336666
  2374.  
  2375.  
  2376.  
  2377.  
  2378.  
  2379.  
  2380. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2381.  
  2382.  
  2383.  
  2384.                   rcb_sw_counters_per_set: 8
  2385.                   rcb_sw_counter_size: 8
  2386.                   rcb_base_pages: 16384
  2387.                   rcb_base_page_size: 16384
  2388.                   rcb_base_paddr: 0xf00000000
  2389.                   rcb_cnodeid: 7
  2390.                   rcb_granularity: 4096
  2391.                   rcb_hw_counter_max: 2047
  2392.                   rcb_diff_threshold: 10
  2393.                   rcb_abs_threshold: 1023
  2394.                   Slot[0]: 0xf00000000 -> 0xf08000000, size: 0x8000000
  2395.                   Slot[1]: 0xf20000000 -> 0xf28000000, size: 0x8000000
  2396.                   Slot[2]: 0xf40000000 -> 0xf40000000, size: 0x0
  2397.                   Slot[3]: 0xf60000000 -> 0xf60000000, size: 0x0
  2398.                   Slot[4]: 0xf80000000 -> 0xf80000000, size: 0x0
  2399.                   Slot[5]: 0xfa0000000 -> 0xfa0000000, size: 0x0
  2400.                   Slot[6]: 0xfc0000000 -> 0xfc0000000, size: 0x0
  2401.                   Slot[7]: 0xfe0000000 -> 0xfe0000000, size: 0x0
  2402.           {FIXED}, sum after 100 loops: 0xee780000
  2403.           page[00000, 0x10004000, 0xa242a0000 (0x2890a8)]: 00000 (000029) 00000 (000007) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2404.           MMAPPED CTRS:  00000 (000029) 00000 (000007) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2405.           page[00001, 0x10005000, 0xa242a1000 (0x2890a8)]: 00000 (000033) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2406.           MMAPPED CTRS:  00000 (000033) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2407.           page[00002, 0x10006000, 0xa242a2000 (0x2890a8)]: 00000 (000032) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2408.           MMAPPED CTRS:  00000 (000032) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2409.           page[00003, 0x10007000, 0xa242a3000 (0x2890a8)]: 00000 (000032) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2410.           MMAPPED CTRS:  00000 (000032) 00000 (000032) 00000 (000000) 00000 (002047) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2411.           page[00004, 0x10008000, 0xb226a4000 (0x2c89a9)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2412.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2413.           page[00005, 0x10009000, 0xb226a5000 (0x2c89a9)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2414.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2415.           page[00006, 0x1000a000, 0xb226a6000 (0x2c89a9)]: 00033 (000000) 00000 (000000) 00000 (000000) 02826 (000180) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2416.           MMAPPED CTRS:  00033 (000000) 00000 (000000) 00000 (000000) 02826 (000180) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2417.           page[00007, 0x1000b000, 0xb226a7000 (0x2c89a9)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2418.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2419.           page[00008, 0x1000c000, 0xb276a8000 (0x2c9daa)]: 00032 (000000) 00000 (000000) 00000 (000000) 03037 (000160) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2420.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03037 (000160) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2421.           page[00009, 0x1000d000, 0xb276a9000 (0x2c9daa)]: 00032 (000000) 00000 (000000) 00000 (000000) 03007 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2422.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03007 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2423.           page[00010, 0x1000e000, 0xb276aa000 (0x2c9daa)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2424.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2425.           page[00011, 0x1000f000, 0xb276ab000 (0x2c9daa)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2426.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2427.           page[00012, 0x10010000, 0xb03eac000 (0x2c0fab)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2428.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2429.           page[00013, 0x10011000, 0xb03ead000 (0x2c0fab)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2430.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2431.           page[00014, 0x10012000, 0xb03eae000 (0x2c0fab)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2432.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2433.           page[00015, 0x10013000, 0xb03eaf000 (0x2c0fab)]: 00032 (000000) 00000 (000000) 00000 (000000) 02975 (000224) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2434.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 02975 (000224) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2435.           page[00016, 0x10014000, 0xb05ab0000 (0x2c16ac)]: 00032 (000000) 00000 (000000) 00000 (000000) 02877 (000214) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2436.  
  2437.  
  2438.  
  2439.                                                                        PPPPaaaaggggeeee 33337777
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446. rrrreeeeffffccccnnnntttt((((5555))))                                                            rrrreeeeffffccccnnnntttt((((5555))))
  2447.  
  2448.  
  2449.  
  2450.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 02877 (000214) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2451.           page[00017, 0x10015000, 0xb05ab1000 (0x2c16ac)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2452.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2453.           page[00018, 0x10016000, 0xb05ab2000 (0x2c16ac)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2454.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2455.           page[00019, 0x10017000, 0xb05ab3000 (0x2c16ac)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2456.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2457.           page[00020, 0x10018000, 0xb242b4000 (0x2c90ad)]: 00032 (000000) 00000 (000000) 00000 (000000) 02976 (000224) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2458.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 02976 (000224) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2459.           page[00021, 0x10019000, 0xb242b5000 (0x2c90ad)]: 00032 (000000) 00000 (000000) 00000 (000000) 03009 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2460.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03009 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2461.           page[00022, 0x1001a000, 0xb242b6000 (0x2c90ad)]: 00035 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2462.           MMAPPED CTRS:  00035 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2463.           page[00023, 0x1001b000, 0xb242b7000 (0x2c90ad)]: 00033 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2464.           MMAPPED CTRS:  00033 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2465.           page[00024, 0x1001c000, 0xb246b8000 (0x2c91ae)]: 00033 (000000) 00000 (000000) 00000 (000000) 03008 (000195) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2466.           MMAPPED CTRS:  00033 (000000) 00000 (000000) 00000 (000000) 03008 (000195) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2467.           page[00025, 0x1001d000, 0xb246b9000 (0x2c91ae)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2468.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2469.           page[00026, 0x1001e000, 0xb246ba000 (0x2c91ae)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2470.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2471.           page[00027, 0x1001f000, 0xb246bb000 (0x2c91ae)]: 00032 (000000) 00000 (000000) 00000 (000000) 03007 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2472.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03007 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2473.           page[00028, 0x10020000, 0xb252bc000 (0x2c94af)]: 00033 (000000) 00000 (000000) 00000 (000000) 02977 (000226) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2474.           MMAPPED CTRS:  00033 (000000) 00000 (000000) 00000 (000000) 02977 (000226) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2475.           page[00029, 0x10021000, 0xb252bd000 (0x2c94af)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2476.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2477.           page[00030, 0x10022000, 0xb252be000 (0x2c94af)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2478.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2479.           page[00031, 0x10023000, 0xb252bf000 (0x2c94af)]: 00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2480.           MMAPPED CTRS:  00032 (000000) 00000 (000000) 00000 (000000) 03008 (000192) 00000 (000000) 00000 (000000) 00000 (000000) 00000 (000000)
  2481.           ricot
  2482.  
  2483.  
  2484.  
  2485. CCCCAAAAVVVVEEEEAAAATTTTSSSS
  2486.      The reference counters are not virtualized. This means that if a process
  2487.      starts paging, or its pages start migrating, the counter set associated
  2488.      with a virtual page will change.
  2489.  
  2490.      The extended memory reference counters may be out of sync with the
  2491.      hardware reference counters by up to the hardware reference counter
  2492.      maximum count (2047 for 11-bit counters and 524287 for 19-bit counters).
  2493.  
  2494.  
  2495. SSSSEEEEEEEE AAAALLLLSSSSOOOO
  2496.      For more information, see numa(5), mmci(5), proc(4), migration(5), sn(1),
  2497.      nstats(1)
  2498.  
  2499.  
  2500.  
  2501.  
  2502.  
  2503.  
  2504.  
  2505.                                                                        PPPPaaaaggggeeee 33338888
  2506.  
  2507.  
  2508.  
  2509.